import sys
import threading
import hashlib
from .aes_algorithm import AES128_UDS
from src.types_pydantic.zlgcan_zuds_types import CanMsg_std_type


def singleton(cls):
    '''
        单例模式的装饰器
    '''
    instances = {}

    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance


def executor_pool_exception_callback(worker):
    '''
        子线程如果报错，将会把子线程错误汇报到主线程中
    '''
    # 将子线程的异常信息记录到日志中
    # 判断一下子线程是否有异常
    worker_exception = worker.exception()
    if worker_exception:
        print(f'[file:{__file__}]=>[line:{
              (sys._getframe().f_lineno)}]==>worker_exception:{worker_exception}')


class PeriodSendThread(object):
    def __init__(self, period_func, args=[], kwargs={}):
        self._thread = threading.Thread(target=self._run)
        self._function = period_func
        self._args = args
        self._kwargs = kwargs
        self._period = 0
        self._event = threading.Event()
        self._period_stop_event = threading.Event()
        self._terminated = False

    def start(self):
        # 启动线程，会卡在_run 的 self._event.wait()处，等待stop，或者 send_start,将_event给set才能继续执行

        self._thread.start()

    def stop(self):
        # 如果执行该函数，因为设置了_terminated，就会跳出while循环，线程执行完毕，线程退出
        self._terminated = True
        self._event.set()
        self._thread.join()

    def send_start(self, period):
        # 如果执行该函数，_run的外层while不会退出，会一直执行self._function(*self._args, **self._kwargs), 直到self._period_stop_event被设置，通过send_stop，置位为False，就会跳出内层while循环
        self._period = period
        self._event.set()

    def send_stop(self):
        self._period_stop_event.set()

    def _run(self):
        while True:
            # 外层循环，当执行start启动，stop退出
            self._event.wait()
            self._event.clear()
            if self._terminated:
                break
            self._function(*self._args, **self._kwargs)
            while not self._period_stop_event.wait(self._period):
                # 内层循环，当执行send_start，send_stop退出
                self._function(*self._args, **self._kwargs)
            self._period_stop_event.clear()


def CANMsg2View_std(msg_frame):
    '''
        转换can报文为id 和 data_list
    '''
    id = msg_frame.can_id
    id_str = hex(id)

    data_list = [msg_frame.data[i] for i in range(msg_frame.can_dlc)]
    data_list_str = [f"{item:02x}" for item in data_list]
    data_str = ''.join(data_list_str)

    return CanMsg_std_type(id=id, id_str=id_str, data_list=data_list, data_list_str=data_list_str, data_str=data_str)
